<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
     <style>
        /* 进度条容器样式 */
        #progress-bar {
            width: 100%;
            background-color: #f3f3f3;
            border-radius: 5px;
            height: 20px;
        }
        /* 进度条填充部分样式 */
        #progress {
            width: 0;
            height: 100%;
            background-color: #4caf50;
            border-radius: 5px;
            text-align: right;
        }

        /* 圆形进度条容器样式 */
        #circle-progress {
            position: relative;
            width: 100px;
            height: 100px;
        }

        /* 圆形进度条SVG旋转 */
        #circle-progress svg {
            transform: rotate(-90deg);
        }

        /* 圆形进度条基础样式 */
        #circle-progress .circle {
            stroke-linecap: round;
            transform: rotate(-90deg);
            transform-origin: 50% 50%;
        }

        /* 圆形进度条背景样式 */
        #circle-progress .circle-background {
            fill: none;
            stroke: #f3f3f3;
            stroke-width: 10;
            stroke-dasharray: 314;
        }

        /* 圆形进度条前景样式 */
        #circle-progress .circle-progress {
            fill: none;
            stroke: #4caf50;
            stroke-width: 10;
            stroke-dasharray: 314;
            stroke-dashoffset: 314;
        }

        /* 进度文字样式 */
        #circle-progress .progress-text {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            font-size: 16px;
        }
    </style>
</head>

<body>
    <!-- 浏览器端网络请求 xhr fetch -->
    <!-- xhr 可以显示上传进度，fetch不行 -->

    <!-- 
     功能点                                XHR              Fetch
     基本请求能力                           √                √
     基本的获取响应能力                     √                √
     监控请求进度                           √                ×
     监控响应进度                           √                √
     Service Worker                        ×                √
     控制cookies携带                        ×                √
     控制重定向                             ×                √
     请求取消                               √                √
     自定义referrer                         ×                √
     流                                     ×                √
     API风格                                Event            Promise
     活跃度                                 停止更新           更新中
     -->
        <!-- 下载开始按钮 -->
        <button onclick="startDownload()">开始下载</button>
        
    <!-- 圆形进度条 -->
    <div id="circle-progress">
        <svg width="100" height="100">
            <!-- 圆形进度条背景 -->
            <circle class="circle-background" cx="50" cy="50" r="45"></circle>
            <!-- 圆形进度条前景 -->
            <circle class="circle-progress" cx="50" cy="50" r="45" id="progress-circle"></circle>
        </svg>
        <!-- 进度文字显示 -->
        <div class="progress-text" id="progress-text">0%</div>
    </div>

    <script>
        // 下载文件的URL
        const url = 'https://vod.v.jstv.com/2025/07/09/JSTV_JSGGNEW_1752061452775_86eouGJ_115.mp4';

        // 原有的 XMLHttpRequest 实现（保留作为参考）
        /*
        function startDownload() {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', url);
            xhr.responseType = 'blob';

            // 监听进度事件
            xhr.addEventListener('progress', (e) => {
                if (e.lengthComputable) {
                    const percentComplete = (e.loaded / e.total) * 100;
                    const progress = document.getElementById('progress')
                    progress.style.width = `${percentComplete}%`;
                    progress.textContent = `${percentComplete.toFixed(2)}%`;
                }
            });

            // 监听加载完成事件
            xhr.onload = function () {
                if (xhr.status === 200) {
                    const blob = xhr.response;
                    const url = window.URL.createObjectURL(blob);
                    const img = document.createElement('video');
                    img.controls = true;
                    img.src = url;
                    document.body.appendChild(img);
                }
            };

            // 发送请求
            xhr.send();
        }
        */

        // 使用 fetch API 的新实现
        async function startDownload() {
            try {
                // 发起fetch请求，获取视频文件
                const response = await fetch(url);
                
                // 检查响应是否成功
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                
                // 获取文件总长度，用于计算下载进度
                const contentLength = response.headers.get('content-length');
                const total = parseInt(contentLength, 10);
                // 已下载的字节数，初始为0
                let loaded = 0;
                
                // 获取响应体的可读流，用于逐步读取数据
                const reader = response.body.getReader();
                // 存储接收到的数据块，最后用于构建完整的文件
                const chunks = [];
                
                // 更新进度显示的函数
                function updateProgress() {
                    // 计算完成百分比，如果总长度未知则显示0%
                    const percentComplete = total ? (loaded / total) * 100 : 0;
                    const progressText = document.getElementById('progress-text');
                    const progressBar = document.getElementById('progress-circle');
                    
                    // 更新圆形进度条
                    // 314是圆的周长(2πr ≈ 2*3.14*45 ≈ 283，这里取近似值314)
                    // stroke-dashoffset控制可见部分的长度，值越小可见部分越多
                    const offset = 314 - (percentComplete / 100) * 314;
                    progressBar.style.strokeDashoffset = offset;
                    progressText.textContent = `${percentComplete.toFixed(2)}%`;
                }
                
                // 读取数据流，使用while循环持续读取直到完成
                while (true) {
                    // 读取下一个数据块，返回一个Promise
                    // done: true表示读取完成，value: 数据块内容
                    const { done, value } = await reader.read();
                    
                    // 如果读取完成，退出循环
                    if (done) break;
                    
                    // 将数据块添加到数组中，用于最后构建完整文件
                    chunks.push(value);
                    // 更新已下载字节数
                    loaded += value.length;
                    // 更新进度显示
                    updateProgress();
                }
                
                // 所有数据读取完成后，创建并显示视频
                // 使用Blob将所有数据块合并成一个完整的文件
                const blob = new Blob(chunks);
                // 创建对象URL，用于在页面中引用这个文件
                const blobUrl = URL.createObjectURL(blob);
                // 创建视频元素并设置属性
                const video = document.createElement('video');
                video.controls = true;  // 显示视频控件（播放/暂停等）
                video.src = blobUrl;    // 设置视频源
                document.body.appendChild(video);  // 添加到页面中
                
            } catch (error) {
                // 处理错误，如网络错误或文件不存在等
                console.error('下载出错:', error);
            }
        }
    </script>
</body>

</html>